import RPi.GPIO as GPIO
import time
import sys
import redis
import json

# 设置GPIO模式为BCM编号
GPIO.setmode(GPIO.BCM)

# 定义L298N控制引脚
IN1 = 17  # GPIO 0 (BCM 17)
IN2 = 18  # GPIO 1 (BCM 18)
IN3 = 27  # GPIO 2 (BCM 27)
IN4 = 22  # GPIO 3 (BCM 22)

# 设置GPIO为输出
GPIO.setup(IN1, GPIO.OUT)
GPIO.setup(IN2, GPIO.OUT)
GPIO.setup(IN3, GPIO.OUT)
GPIO.setup(IN4, GPIO.OUT)

def motor_control(direction, duration=0):
    in1, in2, in3, in4 = IN1, IN2, IN3, IN4
    
    if direction == 'forward':
        GPIO.output(in1, GPIO.HIGH)
        GPIO.output(in3, GPIO.HIGH)
        GPIO.output(in2, GPIO.LOW)
        GPIO.output(in4, GPIO.LOW)
    elif direction == 'backward':
        GPIO.output(in1, GPIO.LOW)
        GPIO.output(in3, GPIO.LOW)
        GPIO.output(in2, GPIO.HIGH)
        GPIO.output(in4, GPIO.HIGH)
    elif direction == 'left':
        GPIO.output(in1, GPIO.HIGH)
        GPIO.output(in3, GPIO.LOW)
        GPIO.output(in2, GPIO.LOW)
        GPIO.output(in4, GPIO.LOW) 
    elif direction == 'right':
        GPIO.output(in1, GPIO.LOW)
        GPIO.output(in3, GPIO.HIGH)
        GPIO.output(in2, GPIO.LOW)
        GPIO.output(in4, GPIO.LOW)    
    elif direction == 'stop':
        GPIO.output(in1, GPIO.LOW)
        GPIO.output(in3, GPIO.LOW)
        GPIO.output(in2, GPIO.LOW)
        GPIO.output(in4, GPIO.LOW)
    else:
        print("错误的方向，请输入'forward', 'backward', 'left', 'right'或'stop'")
        return
    
    if duration > 0:
        time.sleep(duration)
        GPIO.output(in1, GPIO.LOW)
        GPIO.output(in3, GPIO.LOW)
        GPIO.output(in2, GPIO.LOW)
        GPIO.output(in4, GPIO.LOW)

def handle_message(message):
    try:
        data = json.loads(message['data'])
        direction = data.get('direction')
        duration = float(data.get('duration', 0))
        print(f"收到指令: {direction}, 持续时间: {duration}")
        motor_control(direction, duration)
    except Exception as e:
        print(f"处理消息时出错: {e}")

def connect_to_redis():
    retry_count = 0
    max_retries = 100
    
    while retry_count < max_retries:
        try:
            # 连接到Redis服务器
            redis_client = redis.Redis(
                host='www.v110.cc',  # Redis服务器地址
                port=6379,          # Redis端口
                password='gR0gE9xX', # Redis密码
                decode_responses=True
            )
            
            # 创建发布/订阅对象
            pubsub = redis_client.pubsub()
            
            # 订阅控制频道
            pubsub.subscribe('motor_control')
            
            print("成功连接到Redis服务器")
            retry_count = 0  # 连接成功后重置重试计数
            
            # 持续监听消息
            for message in pubsub.listen():
                if message['type'] == 'message':
                    handle_message(message)
                    
        except redis.ConnectionError as e:
            retry_count += 1
            print(f"Redis连接错误: {e}")
            if retry_count < max_retries:
                print(f"10秒后进行第 {retry_count} 次重试... (最多 {max_retries} 次)")
                time.sleep(10)
            else:
                print(f"已达到最大重试次数 {max_retries}，程序退出")
                break
        except KeyboardInterrupt:
            print("程序被用户中断")
            break
        except Exception as e:
            retry_count += 1
            print(f"发生未知错误: {e}")
            if retry_count < max_retries:
                print(f"10秒后进行第 {retry_count} 次重试... (最多 {max_retries} 次)")
                time.sleep(60)
            else:
                print(f"已达到最大重试次数 {max_retries}，程序退出")
                break

if __name__ == "__main__":
    try:
        connect_to_redis()
    finally:
        # 清理GPIO设置
        GPIO.cleanup()
        print("GPIO已清理")